package com.app.Network;

import java.util.ArrayList;
import java.util.Iterator;

import com.app.Activity.MESApplication;
import com.app.Activity.frmBieuQuyetMoiRoiNhom;
import com.app.Activity.frmMainActivity;
import com.app.Activity.frmMatKetNoiActivity;
import com.app.Activity.frmTreeNodeActivity;
import com.app.Activity.trucActivity;
import com.app.Activity.frmNhomChoActivity;
import com.app.Activity.frmNotificationMoiVaoNhom;
import com.app.Activity.frmPhuActivity;
import com.app.Activity.trucActivity;
import com.app.Controller.ActivityController;
import com.app.Controller.NetworkController;
import com.app.Controller.ReadWriteFileController;
import com.app.DTO.AccountDTO;
import com.app.DTO.RoleDTO;

import com.app.Message.PingMessage;
import com.app.Tree.BoardView;
import com.app.Tree.INode;
import com.app.Tree.TextNode;
import com.app.Tree.TreeNode;


import ReadWriteXML.CMember;
import android.os.Handler;
import android.util.Log;
import it.unipr.ce.dsg.s2p.message.Payload;
import it.unipr.ce.dsg.s2p.org.json.JSONException;
import it.unipr.ce.dsg.s2p.org.json.JSONObject;
import it.unipr.ce.dsg.s2p.peer.Peer;
import it.unipr.ce.dsg.s2p.peer.PeerDescriptor;
import it.unipr.ce.dsg.s2p.sip.Address;

public class NetworkLayer extends Peer {
	private Handler hander = new Handler();
	public AccountDTO account = null;

	public AccountDTO getAccount() {
		return this.account;
	}
	public void setAccount(AccountDTO account){
		this.account=account;
	}
	public PeerDescriptor getPeerDescriptor() {
		return this.peerDescriptor;
	}

	public NetworkLayer(String pathConfig, String key, String peerName, int peerPort, AccountDTO account) {
		super(pathConfig, key, peerName, peerPort);
		this.account = account;
	}

	@Override
	protected void onDeliveryMsgFailure(String arg0, Address arg1, String arg2) {
		// TODO Auto-generated method stub

	}

	@Override
	protected void onDeliveryMsgSuccess(String arg0, Address arg1, String arg2) {
		// TODO Auto-generated method stub

	}

	@Override
	protected void onReceivedJSONMsg(JSONObject peerMsg, Address sender) {
		JSONObject params = null;
		//Log.d("Phu", "onReceivedJSONMsg");
		try {
			params = peerMsg.getJSONObject("payload").getJSONObject("params");
		} catch (JSONException e) {

			e.printStackTrace();
			Log.d("Loi", "Lỗi onReceivedJSONMsg try 1");
		}
		try {
			String type = (String) peerMsg.get("type");
			if(!type.equals(Protocol.PING_MSG) && !type.equals(Protocol.PING_MSG_REPLY))
				Log.d("Phu", "type: " + type+" from: "+sender.toString());
			// ===============truc====================================
			//cam noi
			if (type.equals(Protocol.STOP_TALKING_ONE_MEMBER)) {
				NetworkController.NhanYeuCauNgungThaoLuan(params, sender);				
				
			}//tao lao
			else if(type.equals(Protocol.HELLO)){
				NetworkController.ShowMessageNotice("Da nhan hello");
			}
			//cho noi
			else if(type.equals(Protocol.ACCEPT_TALKING_ONE_MEMBER)){
				NetworkController.NhanChoPhepThaoLuan();
			}//chat
			else if(type.equals(Protocol.CHAT_PEER_MESSAGE))
			{
				//truyen thong diep qua ham chat
				Log.d("Phu","da nhan thong diep chat");
				NetworkController.ReceiveMessageChatPeer(params, sender);
				
				//NetworkController.NhanTinNhanTroChuyenRieng(params, sender);
				NetworkController.NhanTinNhanThaoLuan(params, sender);
			}//ko co quyen nhan tin nhan chat
			else if(type.equals(Protocol.CHAT_FEEDBACK_NON_RULE)){
				NetworkController.CloseChatPeerActivity();
				NetworkController.NhanPhanHoiKhongCoQuyenTroChuyenRieng(params, sender);
			}//nhan tin nhan yeu cau bieu quyet moi nguoi khac ra khoi nhom
			else if(type.equals(Protocol.KICK_MEMBER_OUT_MESSAGE)){
				NetworkController.ReceiveVoteKickMember(params, sender);
				
			}//nhan duoc phan hoi moi nguoi khac ra khoi nhom
			else if(type.equals(Protocol.KICK_MEMBER_OUT_FEEDBACK))
			{
				Log.d("Phu","vao fan hoi vote");
			//	NetworkController.ShowMessageNotice("da nhan dc tin nhan phan hoi Kick");
				NetworkController.ReceiveFeedbackKickMember(params);
			}//nhan dc ket qua cuoi dung
			else if(type.equals(Protocol.KICK_MEMBER_OUT_RESULT)){
			//	NetworkController.ShowMessageNotice("da nhan dc ket qua Kick");
				NetworkController.ReceiveResultKickMember(params);
				
			}

			// ==================Phú==========================================

			// Nhận đc gói tin mời vào nhóm
			else if (type.equals(Protocol.GROUP_INVITE)) {
				Log.d("nhan", "nhan dc: " + type);
				if (!account.inGroup) {
					final String contentTitle = params.getString(Protocol.GROUP_INVITE_DATA_GROUP_NAME);
					final String contentText = params.getString(Protocol.GROUP_INVITE_DATA_MSG);
					final Address nguoiGui=sender;
					hander.post(new Runnable() {
						@Override
						public void run() {
							// ActivityController.setPeerActivity(frmPhuActivity.this);
							// ActivityController.showNotification("Có người mời bạn vào nhóm!",
							// contentTitle, contentText);
							NetworkController.sender=nguoiGui;
							ActivityController.showMoiVaoNhomNotification(contentText, contentTitle);
							Log.d("phu", "GROUP_INVITE Nhan duoc"+contentText+"_"+contentTitle);
						}
					});

				} else {

				}
			}
			// Đồng ý vào nhóm
			else if (type.equals(Protocol.GROUP_INVITE_REPLY_YES)) {
				// Kiểm tra tình trạng nhóm xem có vào đc ko - gửi msg từ chối/
				// cho phép vào nóm
				if (frmNhomChoActivity.groupFull) {
					Log.d("phu", "Nhom da full - ko cho vao nhom");
					NetworkController.sendKhongChoVaoNhom(sender);
				} else {
					Log.d("phu", "Cho vao nhom ");
					Log.d("phu", "host: " + sender.getHost());
					NetworkController.sendChoVaoNhom(sender);
					//hander.post(frmPhuActivity.raUpdateNguoiTrongNhom);
				}
			}
			// Không thể vào nhóm - hiện thông báo ko thể vào nhóm
			else if (type.equals(Protocol.GROUP_INVITE_NO)) {
				Log.d("phu", "Ko the vao nhóm ");
				hander.post(frmPhuActivity.raKhongDuocVaoNhom);
			}
			// Có thể vào nhóm -gửi msg join_group
			else if (type.equals(Protocol.GROUP_INVITE_YES)) {
				Log.d("phu", "Có thể vào nhóm");
				// hander.post(frmPhuActivity.raDaVaoNhom);
				hander.post(frmNotificationMoiVaoNhom.raStarNhomCho);
				NetworkController.sendJoinGroup(sender, account.get_Username(), account.get_Username());
			
			}
			// nhận đc tin Vào nhóm - Cập nhật lại member list -
			//  gửi tin cập nhật cho tất cảthành viên
			// Gửi danh sách thành viên cho thằng mới vào
			else if (type.equals(Protocol.JOIN_GROUP)) {
				// Lấy thông tin của member mới vào
				String IP = sender.toString();
				String userName = params.getString(Protocol.MEMBER_USER_NAME);
				String fullName = params.getString(Protocol.MEMBER_FULL_NAME);
				final CMember member = new CMember(IP, fullName, userName);
				
				
				// Cập nhật danh sách member
//				hander.post(new Runnable() {
//					@Override
//					public void run() {
//						Log.d("Phu", "onRecive Json Cập nhật danh sách member");
//						frmNhomChoActivity.insertMember(member);						
//					}
//				});
			
//				final ArrayList<CMember> memberList = ReadWriteFileController
//				.readMember(ReadWriteFileController.MEMBER_PATH);
//				Log.d("Phu","DS TV: "+CMember.toParseList(memberList));
//				//Gửi danh sách thành viên cho thằng mới vào
//				hander.post(new Runnable() {					
//					@Override
//					public void run() {
//						NetworkController.sendMemberList(new Address(member.get_ip()), memberList);
//					}
//				});				
//				
//				// Gửi thông tin cập nhật cho các thành viên 				
//				for (int i = 0; i < memberList.size(); i++) {
//					 {
//						final int j = i;
//						hander.post(new Runnable() {
//							@Override
//							public void run() {								
//								NetworkController.sendUpdateMember(new Address(memberList.get(j).get_ip()), member);
//							}
//						});
//					}
//				}
				frmNhomChoActivity.insertMember(member);	
				final ArrayList<CMember> memberList = ReadWriteFileController.readMember(ReadWriteFileController.MEMBER_PATH);
				NetworkController.sendMemberList(new Address(member.get_ip()), memberList);
				for (int i = 0; i < memberList.size(); i++) {
					 {
						final int j = i;
						hander.post(new Runnable() {
							@Override
							public void run() {								
								NetworkController.sendUpdateMember(new Address(memberList.get(j).get_ip()), member);
							}
						});
					}
				}
				hander.post(frmNhomChoActivity.raRefreshListView);
			}
			//Cập nhật member (insert thêm 1 thành viên)
			else if(type.equals(Protocol.UPDATE_MEMBER_LIST)){
				final String s=params.getString(Protocol.UPDATE_MEMBER_LIST);				
				hander.post(new Runnable() {					
					@Override
					public void run() {
						frmNhomChoActivity.insertMember(CMember.parse(s));						
					}
				});
				hander.post(frmNhomChoActivity.raRefreshListView);
			}
			//Ghi danh sách thành viên xuống file - Hiện màn hình chờ nhóm
			else if(type.equals(Protocol.MEMBER_LIST)){
				final String s=params.getString(Protocol.MEMBER_LIST);				
				ReadWriteFileController.writeMember(ReadWriteFileController.MEMBER_PATH,CMember.parseList(s));
				hander.post(frmNhomChoActivity.raRefreshListView);
				Log.d("Phu","Da mo man hinh Cho nhom trong network");
			}
			// Set role
			else if (type.equals(Protocol.SET_ROLE)) {
				String data = "";
				Iterator<String> iter = params.keys();
				while (iter.hasNext()) {
					String key = iter.next();					
					if (key.equals("DATA")) {
						try {
							data = params.getString(key);
							Log.d("Phu", "SET_ROLE nhận được data:" + data);
							break;
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
				}
				final String s = data;
				hander.post(new Runnable() {

					@Override
					public void run() {
						//Tiến hành ghi xuống file và reset role cho account
						String path = ReadWriteFileController.MY_ROLE_PATH;						
						ReadWriteFileController.writeRole(path,
								RoleDTO.parseList(MESApplication.getAppContext(),s, ReadWriteFileController.RULE_BASE_PATH));
						NetworkController.resetRole();

					}
				});
			}
			//Bắt đầu học nhóm
			else if(type.equals(Protocol.START_GROUP)){
				getAccount().inGroup=true;
				ActivityController.startGroup();
			}
			//Thêm node vào cây
			else if(type.equals(Protocol.ADD_NODE)){
				if(sender.getHost().toString().equals(this.getSimpleIP())){
					return;
				}
				String s=params.getString(Protocol.ADD_NODE);
				long pID=Long.parseLong(params.getString(Protocol.TREENODE_ID));
				TreeNode node=new TreeNode();
				node.parse(s);
				TextNode textnode = new TextNode();
				textnode.parse(s);
//				Log.d("Phu","Da add node khi nhan duoc NetworkLayer ADD_NODE");
//				Log.d("An","pId: "+pID);
//				Log.d("Phu","title: "+node.getTitle());
				frmTreeNodeActivity.idNode=pID;
				frmTreeNodeActivity.nodeAdd=node;
				frmTreeNodeActivity.textnodeAdd=textnode;
				Log.d("Phu"," NetWorkLayer-AddNode..." + frmTreeNodeActivity.isActive);
				if(frmTreeNodeActivity.isActive){
					Log.d("Phu"," NetWorkLayer-AddNode...active nen cho vao cay luon");
					hander.post(frmTreeNodeActivity.raAddnode);
					hander.post(frmTreeNodeActivity.raAddnodetext);
				}
				else{
					Log.d("Phu","NetWorkLayer-AddNode...ko active nen ghi xuong file node: " + node.getId());					
					TreeNode tree = new TreeNode();
					if(ReadWriteFileController.isFile(BoardView.treePath)){							
						tree.readXml(BoardView.treePath);
						Log.d("Phu","NetWorkLayer-AddNode...File tồn tại nên đọc từ file lên: "+tree.getSumChildren());
					}else{
						Log.d("Phu","NetWorkLayer-AddNode...Ko tồn tại file nên createRoot: "+tree.getSumChildren());
						tree=BoardView.createRoot();
					}
					INode temp = tree.getById(pID);
					if (temp != null){
						Log.d("Phu","NetWorkLayer-AddNode...add node: " + node.getId()+" vào node " + temp.getId());
						temp.add(node);
						tree.setVersion(node.getVersion());
						Log.d("Phu","NetWorkLayer-AddNode...add node: " + tree.getSumChildren());
					}
					tree.writeXML(BoardView.treePath);
				}
				
			}
			//Cập nhật text của 1 node
			else if(type.equals(Protocol.UPDATE_NODE_TEXT)){
				String s=params.getString(Protocol.NODE_UPDATE);
				TreeNode node=new TreeNode();
				node.parse(s);
				TextNode textnode = new TextNode();
				textnode.parse(s);
//				frmTreeNodeActivity.idNode=node.getId();
//				frmTreeNodeActivity.textUpdate=node.getText();
//				frmTreeNodeActivity.lb = node.getLabel();
				frmTreeNodeActivity.nodeAdd = node;
				frmTreeNodeActivity.textnodeAdd = textnode;
				if(frmTreeNodeActivity.isActive){
					Log.d("Phu","Active nên update vào cây luôn");
					hander.post(frmTreeNodeActivity.raUpdateTextNode);
					hander.post(frmTreeNodeActivity.raUpdateNodeText);
				}else{
					Log.d("Phu","update ko active cap nhat xuong file");
					TreeNode tree=new TreeNode();
					if(ReadWriteFileController.isFile(BoardView.treePath)){						
						tree.readXml(BoardView.treePath);						
					}else{
						tree=BoardView.createRoot();
					}
					INode temp= tree.getById(node.getId());
					if(temp!=null){
						temp.copy(node);
					}
					tree.writeXML(BoardView.treePath);
				}
			}
			//Xóa node của cây
			else if(type.equals(Protocol.DELETE_NODE_TREE)){
				if (sender.getHost().equals(getSimpleIP()))
					return;
				String s = params.getString(Protocol.DELETE_NODE_TREE);
				INode node=new TreeNode();
				node.parse(s);
				INode tnode = new TextNode();
				tnode.parse(s);
				frmTreeNodeActivity.nodeAdd=(TreeNode) node;
				frmTreeNodeActivity.textnodeAdd = (TextNode)tnode;
				if (frmTreeNodeActivity.isActive) {
					Log.d("An", "active nên delete luôn");
					hander.post(frmTreeNodeActivity.raDeleteNode);
					hander.post(frmTreeNodeActivity.raDeleteNodeText);
				} else {
					Log.d("An", "delete ko active nên xóa ghi xuống file");
					
					TreeNode tree = new TreeNode();
					tree.readXml(BoardView.treePath);
					INode temp = tree.getById(node.getId());
					if (temp != null){
						tree.remove(temp);
						tree.setVersion(node.getVersion());
						tree.writeXML(BoardView.treePath);
					}
					
				}

			}
			//Chat thảo luận
			else if (type.equals(Protocol.CHAT_MESSAGE)) {
				String key;
				if (account.getRuleById(4) != null && account.getRuleById(4).getReceive()) {

					String s = params.getString("Content_Chat");
					NetworkController.ShowMessageChat(s, sender.toString());
					Log.d("Phu", "Da show noi dung chat nhan dc");

				} else {
					Log.d("Phu", "gui phan hoi ko chat net layer");
					NetworkController.ShowMessageNotice("ban ko co quyen nhan tin nhan chat");
					//NetworkController.GuiPhanHoiKhongCoQuyenChat(sender);
				}
			}
			//Ping message
			else if(type.equals(Protocol.PING_MSG)){
				NetworkController.sendPingReply(sender);				
			}
			//Reply ping message
			else if(type.equals(Protocol.PING_MSG_REPLY)){
				NetworkController.setStated(true);
//				frmMatKetNoiActivity.addIP(sender);
			}
			//Nhận đc yêu cầu lấy version cây, sau đó đọc và gửi
			else if(type.equals(Protocol.GET_VERSION)){
				//long version = BoardView.treeversion();
//				Log.d("An", "GET_VERSION-treeVersion: " +version);
				long vs = ReadWriteFileController.getVersionTree();
//				Log.d("An", "GET_VERSION-treeVersion xml..: " +vs);
				NetworkController.sendTreeText(sender, vs);
			}
			//Nhận version tu những peer khac
			else if(type.equals(Protocol.TREE_VERSION)){
				long vs = Long.parseLong(params.getString("TREE_VERSION"));
//				Log.d("An", "TREE_VERSION-treeVersion: " +vs);
				Address address = sender;
				String s = vs+"#"+address;
//				Log.d("An", "TREE_VERSION-s: " +s);
				frmMatKetNoiActivity.addVersion(s);
			}
			else if(type.equals("SEND_VERSION")){
				Log.d("An", "SEND_VERSION: ");
				long vs = Long.parseLong(params.getString("VERSION"));
				TreeNode tree = new TreeNode();
				if(frmTreeNodeActivity.isActive && frmTreeNodeActivity.board!=null){
					tree=frmTreeNodeActivity.board.getTree();
				}else{
					tree.readXml(BoardView.treePath);
				}
				Log.d("An","my vs="+tree.getVersion()+"your vs="+vs);				
				String s = tree.GetStringNode(vs);
				Log.d("An", "SEND_VERSION-node tree: " + s + s.length());
				String del = tree.readDelXML(tree.pathDeleteNode());
				Log.d("An", "SEND_VERSION-delString: "+(del==null));
				NetworkController.sendResultNode(sender, s, del);
			}
			else if(type.equals("RESULT_NODE")){
				String s = params.getString("LIST");
				String dns = params.getString("DELLIST");
				Log.d("An", "RESULT_NODE-dns: " +dns);
				Log.d("An", "RESULT_NODE-s: " +s);
				frmMatKetNoiActivity.NodeString = s;
				frmMatKetNoiActivity.DelNodeString = dns;	
				
				frmMatKetNoiActivity.dongBo(s,dns);
				frmTreeNodeActivity.board.readXml(BoardView.treePath);
				frmTreeNodeActivity.board.autoArrange();
			}
			//end phu
			//-----------------------An-----
			else if (type.equals(Protocol.GROUP_SIGN_OUT)){
				Log.d("PEERDROID", "da nhan tin nhan request sign out");
				NetworkController.ReceiveSignOut(params, sender);
			}else if (type.equals(Protocol.GROUP_DANH_GIA)){
				/*hander.post(new Runnable() {
					
					@Override
					public void run() {
						// TODO Auto-generated method stub
						ActivityController.ShowDanhGia();
					}
				});*/
				NetworkController.ReceiveDanhGia(params, sender);
			}
			else if (type.equals(Protocol.GROUP_BIEU_QUYET)){
				Log.d("PEERDROID", "da nhan tin nhan request bieu quyet");
				NetworkController.ReceiveBieuQuyet(params, sender);
			}
			else if (type.equals(Protocol.RESULT_DANH_GIA)){
				Log.d("PEERDROID", "da nhan tin nhan ket qua danh gia");
				NetworkController.ReceiveResultDanhGia(params, sender);
			}
			else if (type.equals(Protocol.RESULT_BIEU_QUYET)){
				Log.d("PEERDROID", "da nhan tin nhan ket qua bieu quyet");
				NetworkController.ReceiveResultBieuQuyet(params, sender);
			}
			else if (type.equals(Protocol.LOG_FILE)){
				Log.d("PEERDROID", "da nhan Text log");
				NetworkController.ReceiveTextLog(params, sender);
			}
//			else if(type.equals(Protocol.ADD_TEXT_NODE)){
//				String s=params.getString("TEXT_NODE");
//				long nodeID=Long.parseLong(params.getString("TEXT_NODE_ID"));
//				TextNode node=new TextNode();
//				node.parse(s);
//				Log.d("An","Da add node khi nhan duoc NetworkLayer ADD_TEXT_NODE");
//				Log.d("An","pId: "+nodeID);
//				Log.d("An","title "+node.getTitle());
//				frmTreeNodeActivity.idNode=nodeID;
//				frmTreeNodeActivity.textnodeAdd=node;
//				Log.d("Phu","da toi day: " +frmTreeNodeActivity.idNode + " " + frmTreeNodeActivity.textnodeAdd.getTitle());
//				if(frmTreeNodeActivity.isActive){
//					Log.d("An","active nen cho vao cay luon");
//					hander.post(frmTreeNodeActivity.raAddnodetext);
//				}else{
//					Log.d("An","ko active nen ghi xuong file");
//					TextNode tree=new TextNode();
//					tree.readXml(BoardView.treePath);
//					INodeText temp= tree.getById(nodeID);
//					if(temp!=null)
//						temp.add(node);
//					tree.writeXML(BoardView.treePath);
//				}
				
//			}
		} catch (Exception e) {
			// TODO: handle exception
			Log.d("Loi", "Loi trong ham nhận message: "+e.getMessage()+e.getCause());
		}

	}
	//chat rieng========================================
	/**
	 * Hàm gửi thông tin Log out cho giáo viên
	 * @param addr
	 */
	public void SendMessageLogout(Address addr)
	{
		Log.d("PEERDROID","Da vào hàm Gửi Thông tin Logout");
		PingMessage mesage = new PingMessage(peerDescriptor);
		Payload p = new Payload();
		p.addParam("Logout",NetworkController.get_ipUser());
		mesage.setPayload(p);
		mesage.setType("logout");
		send(addr, mesage);
		Log.d("PEERDROID","Da gửi Logout");
	}
	/*-------------Các hàm nhận, gửi thông tin chat, invite group, ...------------*/
	public void SendChatPeerMessage(Address address,String message)
	{//mess gom username/text/ip
		PingMessage newPingMsg = new PingMessage(peerDescriptor);
		Payload pay=new Payload();
		newPingMsg.setType(Protocol.CHAT_PEER_MESSAGE);
		pay.addParam("Message", message);
		newPingMsg.setPayload(pay);
		
		send(address, newPingMsg);
		Log.d("Phu","gui toi: "+address.getURL());
		Log.d("PEERDROID","gui thong diep chat peer");
	}


//end chat rieng==============================
	public String getAddressPeer() {

		return getAddress().getURL();
	}

	public String getContactAddressPeer() {

		return peerDescriptor.getContactAddress();
	}
	public String getSimpleIP(){
		return getAddress().getHost().toString();
	}
	private boolean nhomDaFull() {
		return true;
	}
}
